1 00:00:00,080 --> 00:00:01,220 Welcome back. 2 00:00:01,220 --> 00:00:07,400 In a previous lecture in the Lua basics section, we learned about error messages and handling errors 3 00:00:07,400 --> 00:00:09,350 using the Pcall function. 4 00:00:09,350 --> 00:00:15,860 Now that we're diving into the Roblox API, it's time to continue expanding our error handling arsenal 5 00:00:15,860 --> 00:00:21,890 by taking a look at some of the tools studio offers for debugging errors, and also looking at the documentation 6 00:00:21,890 --> 00:00:25,190 to spot any functions we should wrap in a PE call. 7 00:00:25,190 --> 00:00:25,520 Now. 8 00:00:25,520 --> 00:00:30,970 Earlier we took a look at breakpoints, which are those nifty little things you can add in your scripts, 9 00:00:30,970 --> 00:00:36,760 which will halt the execution of the script, and it will allow you to go line by line, taking a look 10 00:00:36,760 --> 00:00:38,590 at how your code is executing. 11 00:00:38,590 --> 00:00:43,720 But you probably didn't know that there are even more settings that we can access with breakpoints. 12 00:00:43,720 --> 00:00:50,440 So with this example code I have here, I'm going to add a breakpoint at the calling of the main function. 13 00:00:50,440 --> 00:00:57,060 And then we can right click our breakpoint to access a new window for editing some settings in the breakpoint. 14 00:00:57,060 --> 00:01:03,420 In fact, there are some settings where we can have the breakpoint be reached or used. 15 00:01:03,420 --> 00:01:09,540 When only a certain condition is met, we can have it print a message out into the console, and we 16 00:01:09,540 --> 00:01:14,940 can even continue the execution of this script without halting the script and going line by line. 17 00:01:14,940 --> 00:01:21,620 Instead, if we want a breakpoint to act purely as like a log message, then we can hit continue execution, 18 00:01:21,620 --> 00:01:23,990 and then we can print a log message in here. 19 00:01:23,990 --> 00:01:29,690 And then the format of this log message has to be the same as if you were, let's say, putting some 20 00:01:29,690 --> 00:01:31,130 arguments in a print statement. 21 00:01:31,130 --> 00:01:35,540 So for example it says quotation the value of n colon quotation. 22 00:01:35,540 --> 00:01:36,830 And then you do comma n. 23 00:01:36,830 --> 00:01:39,230 If you want to print out a variable in your log message. 24 00:01:39,230 --> 00:01:42,520 We also have an option if we want to delete the breakpoint once we hit it. 25 00:01:42,520 --> 00:01:47,290 So if you only want to reach a breakpoint once when you're debugging, you can enable that setting and 26 00:01:47,290 --> 00:01:50,410 then it will automatically remove the breakpoint for you. 27 00:01:50,410 --> 00:01:53,170 And then we also have some different contexts in here. 28 00:01:53,170 --> 00:01:58,330 So for example, if your breakpoint is in a module script that could get required by the client or the 29 00:01:58,330 --> 00:02:03,580 server, and you only want to debug an error that's occurring on the server, well, you can get rid 30 00:02:03,610 --> 00:02:05,820 of the context on the client. 31 00:02:05,820 --> 00:02:08,070 And then this other context down here called edit. 32 00:02:08,070 --> 00:02:11,280 I believe this is only for plugins, so you don't need to worry about that. 33 00:02:11,280 --> 00:02:14,370 But the two you want to focus on are going to be the client and the server. 34 00:02:14,370 --> 00:02:18,360 But as you can see, there's just a whole bunch of different options here with breakpoints. 35 00:02:18,360 --> 00:02:23,340 So let's go ahead and actually take an example of utilizing some of these settings. 36 00:02:23,340 --> 00:02:28,530 So what I'm going to do is I'm actually going to create a variable before our breakpoint. 37 00:02:28,530 --> 00:02:32,850 Let's just call it uh example var and we're going to set it equal to ten. 38 00:02:32,850 --> 00:02:37,380 Now let's say we only want to reach this breakpoint when example var is equal to 20. 39 00:02:37,380 --> 00:02:41,190 So what we can do is we can type out the variable name which is going to be example var. 40 00:02:41,340 --> 00:02:46,290 And since this has to be an expression we're going to do equal equal 20. 41 00:02:46,290 --> 00:02:50,250 So if this evaluates to true we're going to reach our breakpoint. 42 00:02:50,490 --> 00:02:57,300 And then when we also reach our breakpoint let's go ahead and print a message like the value of example 43 00:02:57,300 --> 00:02:58,680 var is. 44 00:02:58,860 --> 00:03:02,040 We need to close that with quotations since this is a string. 45 00:03:02,040 --> 00:03:05,910 And then we're going to put a comma and then do example var. 46 00:03:05,910 --> 00:03:11,070 So this is the exact same way as if you were typing in arguments for a print statement. 47 00:03:11,070 --> 00:03:14,130 And then we're going to continue execution and not halt the code. 48 00:03:14,130 --> 00:03:15,780 So let's go ahead and save that. 49 00:03:15,780 --> 00:03:21,890 You're going to see that the symbol has changed for our breakpoint, because now it is a log point because 50 00:03:21,890 --> 00:03:23,780 we're printing out a log message. 51 00:03:23,780 --> 00:03:25,820 But let's go ahead and run this code. 52 00:03:27,650 --> 00:03:30,650 And what you're going to see is nothing happened. 53 00:03:30,650 --> 00:03:33,290 We got the print statements that were inside of our function. 54 00:03:33,290 --> 00:03:37,430 For example, it prints before division and then it prints the result after the division. 55 00:03:37,430 --> 00:03:41,150 But you see, it didn't print the message from our log point. 56 00:03:41,150 --> 00:03:44,040 And that's because this condition evaluated to false. 57 00:03:44,070 --> 00:03:50,340 Now if we went and set example of are equal to 20 and then we run it. 58 00:03:50,790 --> 00:03:53,100 As you can see the value of example var is 20. 59 00:03:53,100 --> 00:03:54,570 So our break point was reached. 60 00:03:54,570 --> 00:03:56,280 It printed in the console. 61 00:03:56,280 --> 00:04:00,180 And that's because the condition inside of our break point evaluated to true. 62 00:04:00,180 --> 00:04:05,640 And then it also didn't halt the execution of our script because we have continue execution enabled 63 00:04:05,670 --> 00:04:07,740 If we decide to disable that. 64 00:04:08,940 --> 00:04:12,210 And then actually let me make sure it's disabled, okay, it's disabled. 65 00:04:12,210 --> 00:04:19,200 And then if we were to run the code again, as you can see, we get put inside of the debugging menu. 66 00:04:19,200 --> 00:04:21,780 And now we have to go through line by line inside of our code. 67 00:04:21,780 --> 00:04:24,480 So you should remember the three different options we have. 68 00:04:24,480 --> 00:04:26,970 Step into step over and step out. 69 00:04:26,970 --> 00:04:30,370 So let's go ahead and step into our main function. 70 00:04:30,370 --> 00:04:34,000 Now inside of our main function let's continue stepping. 71 00:04:34,000 --> 00:04:38,440 And then we should be able to print before division they're printed. 72 00:04:38,440 --> 00:04:40,840 And then we're going to step into our divide function. 73 00:04:40,840 --> 00:04:42,520 We're going to perform the division. 74 00:04:42,520 --> 00:04:44,560 And then we print our result. 75 00:04:44,560 --> 00:04:47,020 We reach the end of the scope for this function. 76 00:04:47,020 --> 00:04:50,590 And we go back to where the main function was called. 77 00:04:50,590 --> 00:04:51,670 And we're done. 78 00:04:51,670 --> 00:04:53,800 That's the end of this particular script. 79 00:04:53,910 --> 00:04:59,850 Now another useful thing with breakpoints is that we can add breakpoints while we're running the game, 80 00:04:59,850 --> 00:05:01,740 and that allows us to continue. 81 00:05:01,740 --> 00:05:06,960 Let's say we found a bug somewhere, and we want to figure out what exactly is causing the bug. 82 00:05:06,960 --> 00:05:12,030 So let's say this bug can repeat itself, and then we need to add a new breakpoint somewhere. 83 00:05:12,030 --> 00:05:17,100 Well, while the game is running we can add a breakpoint, and if we want it to print something in the 84 00:05:17,100 --> 00:05:18,540 console, we can totally do that. 85 00:05:18,540 --> 00:05:24,240 We don't have to stop play testing and then go in here and add another print statement in the code, 86 00:05:24,240 --> 00:05:26,100 and then go back and play test again. 87 00:05:26,100 --> 00:05:27,780 We can do it in real time. 88 00:05:27,780 --> 00:05:32,850 So as an example, what we're going to do is we're going to run this exact same code again. 89 00:05:33,510 --> 00:05:37,500 And right now we're currently at the calling of the main function. 90 00:05:37,500 --> 00:05:39,990 Now what I'm going to do is I'm going to add another breakpoint here. 91 00:05:40,410 --> 00:05:42,460 And let's go ahead and edit this breakpoint. 92 00:05:42,460 --> 00:05:47,080 And what we're going to do is we're just going to simply print out what the value of x and y is. 93 00:05:47,080 --> 00:05:49,060 So we can just do x comma y. 94 00:05:49,390 --> 00:05:54,760 And then we're going to have this uh continue execution I'm going to save that. 95 00:05:54,760 --> 00:05:58,390 So we just added a breakpoint while we're in the debugging menu. 96 00:05:58,390 --> 00:06:00,730 And then now let's just step into our code. 97 00:06:01,240 --> 00:06:04,540 So now we create x and y we go to the print statement. 98 00:06:04,540 --> 00:06:09,150 And as you can see it also printed out the value of x and y while we were in the middle of debugging. 99 00:06:09,150 --> 00:06:11,610 So that's another useful thing with breakpoints. 100 00:06:11,610 --> 00:06:17,520 We can just add them while we are in the process of debugging our code. 101 00:06:17,520 --> 00:06:19,410 For example, we can have this one print. 102 00:06:19,410 --> 00:06:28,140 Let's have this one print the results and we'll continue execution and we'll step over to get the result. 103 00:06:29,970 --> 00:06:30,470 There we go. 104 00:06:30,470 --> 00:06:31,970 It printed two, which was the result. 105 00:06:31,970 --> 00:06:35,900 And then we're going to call the print function again which printed two once more. 106 00:06:37,100 --> 00:06:38,030 And then we'll step out. 107 00:06:38,030 --> 00:06:40,370 And then our debugging process is over. 108 00:06:40,370 --> 00:06:41,870 But as you can see that's really cool. 109 00:06:41,870 --> 00:06:45,380 We can add breakpoints in the middle of debugging our code. 110 00:06:45,380 --> 00:06:47,600 We can't do that with regular print statements. 111 00:06:47,990 --> 00:06:51,110 Now we have even more debugging tools at our disposal. 112 00:06:51,110 --> 00:06:55,680 If we head to the view tab, we can open up another window called watch. 113 00:06:55,680 --> 00:07:01,470 And this one's a very interesting window because what it allows us to do is it allows us to watch the 114 00:07:01,470 --> 00:07:04,800 values of variables depending on a particular scope. 115 00:07:04,800 --> 00:07:06,510 And we can filter the scope out too. 116 00:07:06,540 --> 00:07:10,560 So if we hit this button right here that says all scopes, we can actually toggle what scope we want 117 00:07:10,560 --> 00:07:11,430 to look at variables. 118 00:07:11,430 --> 00:07:15,840 If it's going to be a global variable, an up value or a local variable. 119 00:07:15,840 --> 00:07:17,610 And then it also gives you descriptions of each. 120 00:07:17,610 --> 00:07:21,610 So a local variable is accessible only within the block of code where it's declared. 121 00:07:21,610 --> 00:07:26,200 And upvalue is a local variable that an inner function or a loop uses. 122 00:07:26,920 --> 00:07:35,620 So an upvalue would basically be, for example, if we had a variable up here called hello, that's 123 00:07:35,620 --> 00:07:36,370 equal to ten. 124 00:07:36,370 --> 00:07:41,470 If the current thread of execution is inside of our main function, we can access hello. 125 00:07:41,470 --> 00:07:45,640 But hello is not a global variable because we declared it to be local. 126 00:07:45,640 --> 00:07:48,820 But it's also not local to our main function. 127 00:07:48,820 --> 00:07:52,480 So therefore it's considered what we would call an Upvalue. 128 00:07:52,480 --> 00:07:58,480 So what I'm going to do is I'm going to delete these log points, and we're going to go back and run 129 00:07:58,480 --> 00:08:02,170 our code, and we're going to pay attention to this watch menu. 130 00:08:02,170 --> 00:08:04,810 As you can see right now we're in the debugging process. 131 00:08:04,810 --> 00:08:07,100 And we can see a whole bunch of different variables here. 132 00:08:07,100 --> 00:08:10,460 Here are some global variables which we don't really care about right now. 133 00:08:10,460 --> 00:08:14,300 So let's actually hide all of the global variables. 134 00:08:14,540 --> 00:08:19,820 So right now we have access to three different variables in the current scope we're at. 135 00:08:19,820 --> 00:08:22,760 So the current thread of execution is at this line. 136 00:08:22,760 --> 00:08:23,960 In this scope. 137 00:08:23,960 --> 00:08:26,420 And within the scope we can see three different variables. 138 00:08:26,420 --> 00:08:27,860 We can see our main function. 139 00:08:27,860 --> 00:08:31,600 We can see our example variable and we can see our divide function. 140 00:08:31,600 --> 00:08:33,490 And it tells us what the values are as well. 141 00:08:33,490 --> 00:08:35,080 So these two are functions. 142 00:08:35,080 --> 00:08:38,140 And our example variable has a value of 20. 143 00:08:38,140 --> 00:08:41,740 As we continue to step into the code you're going to see these values change. 144 00:08:41,740 --> 00:08:46,480 Right now we can only see divide because we're in the scope of the function. 145 00:08:46,480 --> 00:08:49,180 We're not able to see example var out here. 146 00:08:49,180 --> 00:08:50,770 We can only see divide right now. 147 00:08:50,770 --> 00:08:57,610 But once we create those two variables x and y now they appear inside of the variable section and they're 148 00:08:57,610 --> 00:08:58,480 both local. 149 00:08:58,480 --> 00:09:03,970 And you can also see that it declares that the divide function is an up value, which makes sense because 150 00:09:03,970 --> 00:09:10,000 divide is not a function that's a local to this scope, but it's also not a global function, so it's 151 00:09:10,000 --> 00:09:10,750 an up value. 152 00:09:10,780 --> 00:09:15,970 Now, another useful feature with this watch menu is we can go to this other tab called My Watches. 153 00:09:15,970 --> 00:09:18,700 And it allows you to enter in expressions. 154 00:09:18,710 --> 00:09:23,210 An expression is basically something like a Boolean expression or an arithmetic expression. 155 00:09:23,210 --> 00:09:26,840 It's just a result or a series of executions that produce some kind of result. 156 00:09:26,840 --> 00:09:33,890 So for example, an arithmetic expression would be x plus y and we can hit enter and look at that. 157 00:09:33,890 --> 00:09:36,260 It knows that it produces the value of 15. 158 00:09:36,260 --> 00:09:40,640 If we look at the values of x and y x is ten, y is 15. 159 00:09:40,640 --> 00:09:44,710 And therefore the result of this expression x plus y is 15. 160 00:09:44,710 --> 00:09:48,370 And we can do this while we're in the middle of debugging our code. 161 00:09:48,370 --> 00:09:50,410 We could do x minus y. 162 00:09:50,560 --> 00:09:52,660 We could do x times y. 163 00:09:52,660 --> 00:09:57,730 And as you can see it's going to show us each one of those values based on this expression and what 164 00:09:57,730 --> 00:10:00,040 is currently stored in these variables. 165 00:10:00,370 --> 00:10:04,960 Now let's say we want to see the expression of result plus x or something like that. 166 00:10:04,960 --> 00:10:10,140 We could do result plus X, but right now you're going to see that it says value is not found. 167 00:10:10,140 --> 00:10:13,080 And that's because we're currently on line number nine. 168 00:10:13,080 --> 00:10:15,570 And we haven't created the result variable yet. 169 00:10:15,930 --> 00:10:18,750 So let's continue stepping into our code. 170 00:10:18,750 --> 00:10:20,550 Let's perform the division. 171 00:10:20,550 --> 00:10:22,140 We'll create our result variable. 172 00:10:22,140 --> 00:10:23,220 And there you go. 173 00:10:23,220 --> 00:10:25,830 Now it has a value of result plus x. 174 00:10:25,830 --> 00:10:29,970 Because if we look at the variables tab we can see our result variable. 175 00:10:29,970 --> 00:10:31,920 And that is holding the value of two. 176 00:10:31,950 --> 00:10:35,070 So two plus ten is equal to 12. 177 00:10:35,100 --> 00:10:41,490 Another cool feature while we're in the middle of debugging is that if you hover your mouse over a particular 178 00:10:41,490 --> 00:10:45,660 variable like result and you keep it there, you're going to see a little window pop up and it's going 179 00:10:45,660 --> 00:10:48,180 to tell us what the value is stored in that variable. 180 00:10:48,180 --> 00:10:49,950 So as you can see result is two. 181 00:10:49,980 --> 00:10:50,880 How about x. 182 00:10:50,880 --> 00:10:52,650 Let's take a look at x x is ten. 183 00:10:52,650 --> 00:10:54,600 How about y y is five. 184 00:10:54,600 --> 00:10:56,380 Wow isn't that pretty nifty. 185 00:10:56,380 --> 00:10:59,680 These are all features that print statements can't give you. 186 00:10:59,710 --> 00:11:04,420 Sure, print statements are fast and easy to implement, but breakpoints give you so many more features 187 00:11:04,420 --> 00:11:06,430 that make debugging a breeze. 188 00:11:06,430 --> 00:11:11,980 Whether it's a logical error, whether it is a runtime error, using breakpoints can make the debugging 189 00:11:11,980 --> 00:11:16,120 process very fast, especially in conjunction with this watch menu. 190 00:11:16,120 --> 00:11:21,990 Let me slap in a few more expressions inside of the My Watch's menu, for example, is result greater 191 00:11:21,990 --> 00:11:23,040 than x? 192 00:11:23,670 --> 00:11:24,420 It's false. 193 00:11:24,420 --> 00:11:24,840 Of course. 194 00:11:24,840 --> 00:11:26,220 Result is not greater than x. 195 00:11:26,220 --> 00:11:28,590 Is x greater than result. 196 00:11:28,590 --> 00:11:32,400 Ah, that's true because x is ten, result is two. 197 00:11:32,820 --> 00:11:36,780 How about let's do a little bit more of a complex boolean expression. 198 00:11:36,780 --> 00:11:47,250 Is x greater than um let's say y and let's say result is greater than y. 199 00:11:47,670 --> 00:11:54,330 Oh that's false because x is ten, y is five, result is 12 and y is five. 200 00:11:54,330 --> 00:11:58,320 So this evaluated to false because not both conditions were true. 201 00:11:58,320 --> 00:12:01,950 So like I said there's a lot of different possibilities you can do with this. 202 00:12:01,950 --> 00:12:05,070 My watches section in the watch menu. 203 00:12:05,070 --> 00:12:09,620 Now one more debugging menu I'd like to show you is going to be something called the Script Analysis 204 00:12:09,620 --> 00:12:12,050 window, which you might have seen open down here. 205 00:12:12,080 --> 00:12:17,690 And basically what this script analysis window does is it'll show you any compile time errors or any 206 00:12:17,690 --> 00:12:22,940 warnings inside of your scripts, whether that's type annotation warnings, whether you made a mistake 207 00:12:22,940 --> 00:12:28,280 in your code somewhere, it's going to spit out those warnings in here and it'll tell you what script 208 00:12:28,280 --> 00:12:29,780 that warning is coming from. 209 00:12:29,780 --> 00:12:34,990 So as an example, let's say we made a really silly mistake with our main function and we forgot an 210 00:12:34,990 --> 00:12:38,290 end statement to close out the scope of the main function. 211 00:12:38,290 --> 00:12:44,800 Well, as you can see in the script analysis window, we have an error expected end to close function 212 00:12:44,800 --> 00:12:46,120 at line six. 213 00:12:46,120 --> 00:12:48,220 And instead we got end of file. 214 00:12:48,280 --> 00:12:50,200 So we can click that. 215 00:12:50,200 --> 00:12:52,390 It's going to highlight the error. 216 00:12:52,390 --> 00:12:54,190 As you can see the underline is right here. 217 00:12:54,190 --> 00:12:55,980 And it says the exact same error message. 218 00:12:56,040 --> 00:12:59,730 But it says we need to close a function at line six. 219 00:12:59,730 --> 00:13:06,480 So if we go up to line six here's our function and we can realize, oh silly me, I forgot to put an 220 00:13:06,480 --> 00:13:08,910 end statement here to close out the main function. 221 00:13:08,910 --> 00:13:12,420 And as you can see, the error is now gone from the script analysis window. 222 00:13:12,450 --> 00:13:18,240 I personally use the script analysis window while I am scripting, just in case any errors appear in 223 00:13:18,240 --> 00:13:19,850 other scripts while I'm modifying. 224 00:13:19,850 --> 00:13:24,410 Let's say a module that is used by other scripts when I am modifying that module. 225 00:13:24,410 --> 00:13:26,450 If any other script that's using it. 226 00:13:26,570 --> 00:13:29,810 Um, let's say an error occurs because I made a stupid mistake in the module. 227 00:13:29,810 --> 00:13:32,870 All of those errors will pop up inside of the script analysis window. 228 00:13:32,870 --> 00:13:35,120 So I can go ahead and take a look at what the issue is. 229 00:13:35,120 --> 00:13:39,290 Here I have some example code that we're going to practice using breakpoints with. 230 00:13:39,290 --> 00:13:45,580 This code produces an intermittent error and that occurs when this random number generator produces 231 00:13:45,580 --> 00:13:46,960 a value of zero. 232 00:13:46,960 --> 00:13:52,210 And that's because we are not able to divide by zero when we divide a number by zero. 233 00:13:52,240 --> 00:13:57,370 This divide function is going to return a number called Nan, which is basically an invalid number. 234 00:13:57,370 --> 00:14:00,430 It's a number, but we shouldn't be using it in our code. 235 00:14:00,430 --> 00:14:07,060 And the issue with this is that if this returns Nan, when we try to set an index in our table that 236 00:14:07,060 --> 00:14:11,730 we're creating right here, and we try to set it with the index of Nan, we're going to run into a problem. 237 00:14:11,730 --> 00:14:16,920 And this only happens intermittently if the random number generator generates a value of zero. 238 00:14:16,920 --> 00:14:20,940 So what we're going to do is we're going to run this code and we're going to see how long it's going 239 00:14:20,940 --> 00:14:22,980 to take for us to reach an error. 240 00:14:23,700 --> 00:14:24,990 So we're going to run it. 241 00:14:24,990 --> 00:14:27,150 So far we're having no issues. 242 00:14:27,150 --> 00:14:28,260 Oh and there we go. 243 00:14:28,260 --> 00:14:30,060 We got an error table. 244 00:14:30,060 --> 00:14:31,680 Index is Nan. 245 00:14:31,680 --> 00:14:33,890 but our code is still continuing to run. 246 00:14:33,890 --> 00:14:39,920 And as you can see, this error is only happening when that random number generator produces a value 247 00:14:39,920 --> 00:14:40,760 of zero. 248 00:14:40,760 --> 00:14:47,660 So what we're going to do right now is we're going to pause the game because we need to start debugging. 249 00:14:47,660 --> 00:14:50,510 So as you can see the viewport is paused for debugging. 250 00:14:50,510 --> 00:14:53,630 We're going to hop into our script where the error is occurring. 251 00:14:53,630 --> 00:14:54,740 So we can click this. 252 00:14:54,770 --> 00:14:57,800 It's going to show us the line that the error is occurring. 253 00:14:57,800 --> 00:15:00,470 And we need to figure out why this is happening. 254 00:15:00,470 --> 00:15:05,480 So because we're in the debugging process, we are able to add in breakpoints right away to see what 255 00:15:05,480 --> 00:15:06,470 the heck is going on. 256 00:15:06,470 --> 00:15:12,380 So since we know the error is happening right here, let's add a breakpoint above just to see what the 257 00:15:12,380 --> 00:15:16,340 value of x and y is going to be and what the value of result is going to be. 258 00:15:16,340 --> 00:15:19,160 So let's go ahead and resume. 259 00:15:19,950 --> 00:15:21,450 We're going to hit that break point. 260 00:15:21,450 --> 00:15:24,570 And now we are at this line of before division. 261 00:15:24,570 --> 00:15:27,330 So let's go ahead and step into that. 262 00:15:27,660 --> 00:15:28,770 Let's see what we print. 263 00:15:28,770 --> 00:15:30,210 We print it out before Division. 264 00:15:30,210 --> 00:15:32,460 Let's continue stepping into the code. 265 00:15:33,090 --> 00:15:36,090 We're going to get a slash B and we're going to get a result. 266 00:15:36,120 --> 00:15:39,570 Now let's go ahead and open up our watch menu. 267 00:15:40,410 --> 00:15:43,680 And let's go ahead and take a look at what the current values are. 268 00:15:43,680 --> 00:15:47,570 So x is currently one, y is currently negative one. 269 00:15:47,570 --> 00:15:51,440 And our result is a value of negative one. 270 00:15:51,440 --> 00:15:53,720 Let's continue stepping into the code. 271 00:15:54,770 --> 00:15:59,510 Prints my table with a key of negative one. 272 00:15:59,510 --> 00:16:03,500 Now typically you don't want to have tables with negative keys but that doesn't produce an error. 273 00:16:03,500 --> 00:16:04,190 So it's fine. 274 00:16:04,190 --> 00:16:07,700 And let's just continue stepping through the code. 275 00:16:07,730 --> 00:16:11,210 Actually let's step into okay we're back at the breakpoint again. 276 00:16:11,210 --> 00:16:14,120 Let's see what the value of x and y is this time okay. 277 00:16:14,120 --> 00:16:15,320 They're both negative one. 278 00:16:15,320 --> 00:16:20,210 So we'll just continue stepping into the code see what result is. 279 00:16:20,210 --> 00:16:22,070 Result is one okay. 280 00:16:22,070 --> 00:16:23,090 No issues. 281 00:16:23,420 --> 00:16:25,340 We're going to continue going through the code. 282 00:16:26,300 --> 00:16:27,230 All right this time. 283 00:16:27,230 --> 00:16:30,830 Look at that x is negative one y is zero. 284 00:16:30,830 --> 00:16:35,060 So at this point if you're a good developer you should already recognize we're going to run into an 285 00:16:35,060 --> 00:16:35,480 issue. 286 00:16:35,480 --> 00:16:37,670 But let's continue stepping into the code. 287 00:16:37,670 --> 00:16:40,730 Let's perform our division and let's get our result variable. 288 00:16:40,850 --> 00:16:44,270 And result is actually negative infinity. 289 00:16:45,140 --> 00:16:49,670 So inside of our table, if we set that I don't think we're going to actually run into an issue okay. 290 00:16:49,670 --> 00:16:51,020 No we didn't run into an issue. 291 00:16:51,620 --> 00:16:54,020 So let's just keep going through the code. 292 00:16:54,050 --> 00:16:56,880 This time x is zero y is negative one. 293 00:16:56,880 --> 00:16:58,080 Let's keep going. 294 00:17:00,990 --> 00:17:03,030 Okay no issues so far. 295 00:17:03,300 --> 00:17:06,330 And as you can see x and y are now both zero. 296 00:17:06,570 --> 00:17:10,740 So let's see what result variable or the value we get in result. 297 00:17:10,740 --> 00:17:11,520 And look at that. 298 00:17:11,520 --> 00:17:14,610 Finally we have reached the crux of the problem. 299 00:17:14,610 --> 00:17:21,860 We have gotten Nan which is a problem because if we try to set that in the table, boom, we get our 300 00:17:21,860 --> 00:17:22,340 error. 301 00:17:22,520 --> 00:17:25,730 So now we have a pretty good idea of why this error is occurring. 302 00:17:25,730 --> 00:17:28,370 Let's go ahead and try to fix it in our code. 303 00:17:28,520 --> 00:17:35,420 Now one way we could fix it is we could basically say, hey, you know, if y is zero, let's just not 304 00:17:35,420 --> 00:17:41,120 do anything, but let's add in some error handling inside of the divide function. 305 00:17:41,120 --> 00:17:44,390 Or actually let's throw an error if we try to divide by zero. 306 00:17:44,410 --> 00:17:52,900 So if b is equal to zero, then we're just going to throw an error that we cannot divide by zero. 307 00:17:53,860 --> 00:17:55,690 And then we need to handle this error. 308 00:17:55,690 --> 00:17:57,970 So this is where Paul is going to come into play. 309 00:17:57,970 --> 00:18:00,310 So let's go ahead and do pcall. 310 00:18:01,060 --> 00:18:06,160 And we're going to call the divide function and pass x and y. 311 00:18:06,460 --> 00:18:08,230 And we need to get that result back. 312 00:18:08,230 --> 00:18:09,690 So let's return it. 313 00:18:09,810 --> 00:18:14,250 And then this p call is going to give us a boolean of whether or not we were successful in executing 314 00:18:14,250 --> 00:18:16,890 the code as well as our result. 315 00:18:16,890 --> 00:18:18,960 So now we can go ahead and get rid of this. 316 00:18:19,110 --> 00:18:25,860 And now what we can do before we set result inside of our table, we need to check if we were successful, 317 00:18:26,550 --> 00:18:28,680 if we were not successful. 318 00:18:28,680 --> 00:18:30,390 So let's do not. 319 00:18:30,960 --> 00:18:34,970 Then we're just going to return and do nothing. 320 00:18:35,060 --> 00:18:38,570 And maybe we can print out a message of the error. 321 00:18:38,570 --> 00:18:43,880 Maybe we'll put a warning here and we'll print out what the result was from this call, which should 322 00:18:43,880 --> 00:18:46,190 be the error message if we were not successful. 323 00:18:46,400 --> 00:18:51,230 And then let's go ahead and re-add our breakpoint right here and let's run the code again. 324 00:18:51,380 --> 00:18:53,840 So now we're back in the debugging process. 325 00:18:53,840 --> 00:18:58,810 Let's step into our code Okay, pretty lucky we got both zero and zero. 326 00:18:58,810 --> 00:19:01,030 So this should produce an error. 327 00:19:01,030 --> 00:19:05,620 So if we step into this we do that we're going to get our error. 328 00:19:05,620 --> 00:19:07,420 Boom error happened. 329 00:19:07,420 --> 00:19:10,270 As you can see success is set to false. 330 00:19:10,270 --> 00:19:15,820 And the result is what result is probably a string right. 331 00:19:15,820 --> 00:19:16,300 Yeah. 332 00:19:16,300 --> 00:19:20,290 There's our string value cannot divide by zero. 333 00:19:21,120 --> 00:19:24,630 So if we step into this we're obviously not successful. 334 00:19:24,630 --> 00:19:27,300 We're going to get a warning printed out in the console. 335 00:19:27,300 --> 00:19:28,680 Cannot divide by zero. 336 00:19:29,130 --> 00:19:32,670 And then we just return and we move on to the next iteration of the loop. 337 00:19:32,670 --> 00:19:38,400 And just like that, we have fixed our intermittent bug by handling it with a p call. 338 00:19:38,430 --> 00:19:38,970 All right. 339 00:19:38,970 --> 00:19:43,230 So the last thing we're going to do is we're going to hop into the Roblox documentation. 340 00:19:43,230 --> 00:19:50,210 And we're going to look around to see if a function in some kind of service needs p call to be used 341 00:19:50,210 --> 00:19:50,570 on it. 342 00:19:50,570 --> 00:19:55,970 Because as a Roblox developer, you need to be aware that there are certain functions in the Roblox 343 00:19:55,970 --> 00:19:58,550 API that may produce an error. 344 00:19:58,550 --> 00:20:03,290 Typically, these functions end with the word async, meaning asynchronous. 345 00:20:03,290 --> 00:20:09,130 Those functions make some kind of web requests to the Roblox servers and due to issues outside of your 346 00:20:09,130 --> 00:20:12,250 control, maybe there's some kind of internet issue or something. 347 00:20:12,250 --> 00:20:17,740 It might return some kind of HTTP error, and we need to be able to handle that using HTTP call. 348 00:20:17,740 --> 00:20:21,490 So let's go search through the documentation and let's go to our random service. 349 00:20:21,490 --> 00:20:23,440 Like let's go to the player service right. 350 00:20:24,130 --> 00:20:25,630 We'll go to the player service. 351 00:20:25,630 --> 00:20:32,170 And let's say we want to get the thumbnail picture of a player's head right. 352 00:20:32,170 --> 00:20:35,220 So let's see if there's a function in here somewhere for that. 353 00:20:35,580 --> 00:20:36,690 Ah yes here it is. 354 00:20:36,720 --> 00:20:39,240 Get user thumbnail and look at that. 355 00:20:39,240 --> 00:20:41,700 It says async and this function yields. 356 00:20:41,700 --> 00:20:47,670 So it says this function returns the content URL of an image of a player's avatar given their user id. 357 00:20:47,670 --> 00:20:52,620 So this function makes a web request and web requests can possibly fail. 358 00:20:52,620 --> 00:20:57,120 So this is an example of a function that we need to wrap an API call. 359 00:20:57,180 --> 00:20:58,770 So let's practice doing that. 360 00:20:58,770 --> 00:21:02,520 Let's grab the player service game, get service players. 361 00:21:02,670 --> 00:21:05,490 And every time a player joins our game. 362 00:21:05,490 --> 00:21:07,830 So we'll listen to the player added event. 363 00:21:07,830 --> 00:21:10,800 We'll connect a Lambda function to that. 364 00:21:10,800 --> 00:21:14,280 And this function is going to be passed the player that has joined our game. 365 00:21:14,850 --> 00:21:22,850 And we want to get the image ID of the thumbnail for this player's head so we can use the player service 366 00:21:22,850 --> 00:21:23,450 function. 367 00:21:23,450 --> 00:21:30,740 Get user thumbnail async I need to give it the user id of the player, so we can just do player dot 368 00:21:30,740 --> 00:21:31,520 user id. 369 00:21:31,580 --> 00:21:33,410 We need to give it a thumbnail type. 370 00:21:33,410 --> 00:21:36,530 So enum dot thumbnail type dot. 371 00:21:36,530 --> 00:21:37,730 Let's do a headshot. 372 00:21:38,300 --> 00:21:39,980 And what else do we need to pass to it. 373 00:21:39,980 --> 00:21:44,990 We need to pass the thumbnail size so we can do enum dot thumbnail size. 374 00:21:45,220 --> 00:21:48,370 And let's just do 180 by 180 pixels. 375 00:21:48,910 --> 00:21:53,050 And then let's go ahead and print out this image ID into the console. 376 00:21:53,050 --> 00:21:57,970 Now, it isn't likely that I'm going to run into an error because I'm not experiencing any network issues, 377 00:21:57,970 --> 00:22:01,510 but this is a function we should wrap in a p call. 378 00:22:01,510 --> 00:22:05,170 Otherwise if it errors, we're going to have problems in our code. 379 00:22:05,170 --> 00:22:11,500 So what we should do instead is we should call p Pcall, and we're going to pass a lambda function to 380 00:22:11,500 --> 00:22:11,980 this. 381 00:22:11,980 --> 00:22:15,550 And we're going to return the result of this function right here. 382 00:22:15,550 --> 00:22:19,780 So let's cut that and then let's paste that here. 383 00:22:20,170 --> 00:22:21,580 And we're going to return it. 384 00:22:21,580 --> 00:22:25,030 So this should return to us success. 385 00:22:25,030 --> 00:22:26,500 And then the result. 386 00:22:27,850 --> 00:22:35,000 And then if we were not successful then we can simply spit out a warning, which is going to be the 387 00:22:35,000 --> 00:22:35,870 error message. 388 00:22:36,380 --> 00:22:43,610 Otherwise, if we were successful, we can go ahead and, you know, print out our image ID, which 389 00:22:43,610 --> 00:22:45,650 is going to be equal to the results. 390 00:22:45,740 --> 00:22:48,200 I mean, technically I don't need this middleman variable. 391 00:22:48,200 --> 00:22:51,320 I could just print out results directly. 392 00:22:52,280 --> 00:22:55,400 And now let's go ahead and play test the game and see what happens. 393 00:22:56,450 --> 00:22:56,930 There we go. 394 00:22:56,930 --> 00:23:04,910 I got my IRL RGB thumbnail for my particular user ID and the width and the height. 395 00:23:04,940 --> 00:23:05,750 Pretty cool. 396 00:23:05,750 --> 00:23:10,820 And we can use this in like image labels and stuff to display, uh, the headshot of my character. 397 00:23:10,820 --> 00:23:13,070 But as you can see, no network issue. 398 00:23:13,220 --> 00:23:17,240 What I'm going to do is I'm going to artificially insert an error in here. 399 00:23:17,900 --> 00:23:21,380 We're just going to say some network error happened. 400 00:23:23,760 --> 00:23:25,560 And then let's go ahead and playtest the game. 401 00:23:25,890 --> 00:23:26,490 There we go. 402 00:23:26,490 --> 00:23:31,080 Some network error happened, but we did not halt the execution of the code. 403 00:23:31,080 --> 00:23:32,910 We did not have an error message appeared. 404 00:23:32,910 --> 00:23:35,220 We simply printed a warning into the console. 405 00:23:35,220 --> 00:23:40,770 And if you had any other code down here that still needed to execute, no matter you successfully got 406 00:23:40,770 --> 00:23:45,600 the user thumbnail or not, we are able to execute that code and we're not going to have any issues. 407 00:23:45,600 --> 00:23:49,670 There are a lot more functions in the API that we need to use pickle on. 408 00:23:49,670 --> 00:23:53,000 For example, get user id from name async. 409 00:23:53,000 --> 00:23:56,570 This is another asynchronous function that we should wrap an API call. 410 00:23:56,600 --> 00:23:57,800 Let's keep looking. 411 00:23:58,310 --> 00:24:00,620 Get name from user id async. 412 00:24:00,620 --> 00:24:03,050 Here's another function we need to wrap in API call. 413 00:24:03,290 --> 00:24:06,260 Get humanoid description from user id. 414 00:24:06,380 --> 00:24:11,380 This one doesn't have async in it, but this is a function that does yield. 415 00:24:11,380 --> 00:24:17,470 It's asynchronous, and because it does make a web request, we should also wrap this one in AP call. 416 00:24:17,500 --> 00:24:18,760 Same thing with this one. 417 00:24:18,760 --> 00:24:22,780 Get humanoid description from outfit id it also yields because it makes a web request. 418 00:24:22,780 --> 00:24:25,060 So we should wrap it AP call. 419 00:24:25,060 --> 00:24:26,140 Same thing with this one. 420 00:24:26,140 --> 00:24:27,640 Get friends async. 421 00:24:27,640 --> 00:24:29,560 Another one we should wrap in AP call. 422 00:24:29,560 --> 00:24:33,340 So there's actually a lot in the player service that we should be wrapping in a p call. 423 00:24:33,340 --> 00:24:35,910 Get character appearance info asynchronous. 424 00:24:35,910 --> 00:24:37,560 Another one we need to wrap in a p call. 425 00:24:37,590 --> 00:24:38,070 Let's see. 426 00:24:38,070 --> 00:24:40,740 Create humanoid model from user id this one also yield. 427 00:24:40,740 --> 00:24:46,170 So I assume that we should also use p call on this just in case because it does make a web request. 428 00:24:46,530 --> 00:24:48,240 Create humanoid model from description. 429 00:24:48,240 --> 00:24:51,630 Another one we should use p call on ban async. 430 00:24:51,660 --> 00:24:53,550 Obviously we should use p call on this one. 431 00:24:53,550 --> 00:24:57,390 By the way, this is a new function that you can have banned players, which is pretty cool. 432 00:24:57,770 --> 00:24:58,460 Team chat. 433 00:24:58,460 --> 00:25:00,680 That is a plugin property or something. 434 00:25:00,680 --> 00:25:02,840 So we don't need to worry about any of these ones. 435 00:25:03,320 --> 00:25:04,460 Get players. 436 00:25:04,460 --> 00:25:08,210 Obviously this is not a function you need to use p call on. 437 00:25:08,210 --> 00:25:08,960 It doesn't yield. 438 00:25:08,960 --> 00:25:10,340 That doesn't make any web requests. 439 00:25:10,370 --> 00:25:12,050 No need for P call on that one. 440 00:25:12,740 --> 00:25:16,940 And then we have some other functions we don't need to use p call on okay. 441 00:25:16,940 --> 00:25:17,510 Pretty cool. 442 00:25:17,510 --> 00:25:19,160 Let's take a look at another service. 443 00:25:19,340 --> 00:25:20,030 Alrighty. 444 00:25:20,060 --> 00:25:23,840 Here's another service that has a lot of methods or functions inside of it. 445 00:25:23,840 --> 00:25:27,140 We should be wrapping in P call and that's the marketplace service. 446 00:25:27,140 --> 00:25:30,920 Let's just go ahead and look through here and see if we can immediately find some functions. 447 00:25:30,920 --> 00:25:33,410 We should use P call on this one. 448 00:25:33,410 --> 00:25:33,860 We shouldn't. 449 00:25:33,860 --> 00:25:36,230 These are just prompting UI for players. 450 00:25:36,230 --> 00:25:40,460 There's no yielding and there is no network requests being made here. 451 00:25:40,460 --> 00:25:43,010 We don't have to handle any errors with these functions. 452 00:25:43,010 --> 00:25:48,550 But let's keep an eye out for any functions that are tagged as yielding, or if they have the word async 453 00:25:48,550 --> 00:25:49,900 in the end of their name. 454 00:25:50,710 --> 00:25:52,420 So let's keep looking. 455 00:25:52,450 --> 00:25:53,200 Oh, here we go. 456 00:25:53,200 --> 00:25:54,160 Here's one right here. 457 00:25:54,160 --> 00:25:55,900 Get developer products. 458 00:25:55,900 --> 00:26:02,260 Async returns a pages object which contains information for all of the current experiences developer 459 00:26:02,260 --> 00:26:02,830 products. 460 00:26:02,830 --> 00:26:04,240 This function yields. 461 00:26:04,240 --> 00:26:06,640 It's an asynchronous function and makes a web request. 462 00:26:06,640 --> 00:26:09,220 This is a function we should wrap in p call. 463 00:26:10,950 --> 00:26:11,760 Here's another one. 464 00:26:11,760 --> 00:26:13,260 Get product info. 465 00:26:13,290 --> 00:26:16,710 This one doesn't have the word async in its name, but it does yield. 466 00:26:16,710 --> 00:26:23,880 And it does make a web request to get information about a particular product in the Roblox catalog or 467 00:26:23,880 --> 00:26:24,750 something like that. 468 00:26:24,750 --> 00:26:27,480 So this is another function we should use Pcall on. 469 00:26:27,480 --> 00:26:34,700 And by this point, you should have a pretty good idea of what functions in the API you should be catching 470 00:26:34,700 --> 00:26:35,450 errors with. 471 00:26:35,450 --> 00:26:35,660 Like. 472 00:26:35,660 --> 00:26:38,630 Here's another one you need to watch out for errors with this function. 473 00:26:38,630 --> 00:26:40,640 You need to watch out for errors with this function. 474 00:26:40,640 --> 00:26:42,440 So there's a whole bunch of different ones in here. 475 00:26:42,440 --> 00:26:45,560 It's pretty easy to spot if it has async in the name. 476 00:26:45,560 --> 00:26:46,580 Use P call. 477 00:26:46,580 --> 00:26:47,600 If it yields. 478 00:26:47,600 --> 00:26:54,020 You'll likely need to use p call if any of the definitions of the function talk about making web requests 479 00:26:54,020 --> 00:26:57,140 or anything, you should probably use p call. 480 00:26:57,140 --> 00:27:01,030 So that is all from me for this lecture. 481 00:27:01,030 --> 00:27:07,900 Yes, this lecture was likely a bit boring, but as a Roblox developer, it is super important for you 482 00:27:07,900 --> 00:27:12,400 to understand how to debug errors and how to handle errors using Pcall. 483 00:27:12,400 --> 00:27:17,230 This is one aspect of the development world that you cannot skip and you cannot bypass. 484 00:27:17,230 --> 00:27:19,540 You need to learn this stuff otherwise. 485 00:27:19,540 --> 00:27:22,870 Thank you for watching and I will see you in the next lecture.